<?php
/**
 * @copyright (C) 2011-2012 WebProduction (tm) <webproduction.com.ua>
 *
 * This program is commercial software; you cannot redistribute it and/or
 * modify.

 * @author Maxim Miroshnichenko <max@webproduction.com.ua>
 * @copyright WebProduction
 */
class Triumph_UserService extends ServiceUtils_UserService {

    /**
     * @return User
     */
    public function getUsersAll() {
        $x = parent::getUsersAll();
        $x->setOrder(array('name', 'login'), 'ASC');
        return $x;
    }

    /**
     * @return User
     */
    public function addUser($login, $password, $email, $name, $phone, $address, $bdate, $parentid, $level = false, $commentadmin = false, $logniza = false) {
        try {
            SQLObject::TransactionStart();

            $name = trim($name);
            $login = trim($login);
            $email = trim($email);
            $phone = trim($phone);
            $address = trim($address);
            $bdate = trim($bdate);
            $parentid = trim($parentid);
            $activate = BC::Get()->getSettingsService()->getSettingValue('user-account-activate');

            $ex = new ServiceUtils_Exception();
            if (!$logniza){
                if (!empty($login)) {
                    if (!Checker::CheckLogin($login)) {
                        $ex->addError('login');
                    } else {
                        $user = new User();
                        $user->setLogin($login);
                        if ($user->select()) {
                            $ex->addError('login-exists');
                        }
                    }
                } else {
                    $ex->addError('nologin');
                }

                if (!empty($password)) {
                    if (!Checker::CheckPassword($password)) {
                        $ex->addError('password');
                    }
                } else {
                    $ex->addError('nopassword');
                }
                if(!$commentadmin) {
                    if (!empty($email)) {
                        if (!Checker::CheckEmail($email)) {
                            $ex->addError('email');
                        } else {
                            $user = new User();
                            $user->setEmail($email);
                            if ($user->select()) {
                                $ex->addError('email-exists');
                            }
                        }
                    }else {
                        $ex->addError('noemail');
                    }
                }

                if (!empty($parentid)) {
                    try {
                        !$this->getUserByID($parentid);
                    }catch (Exception $e){
                        $ex->addError('parentid');
                    }
                }

                /*if (!empty($bdate)) {
                    if (!Checker::CheckDate($bdate)) {
                        $ex->addError('bdate');
                    }
                }*/

                if (!empty($phone)) {
                    if (!Checker::CheckPhone($phone)){
                        $ex->addError('phone');
                    }
                }

                if ($ex->getCount()) {
                    throw $ex;
                }
            }
            
            $user = new User();
            $user->setCdate(date('Y-m-d H:i:s'));
            $user->setEmail($email);
            $user->setLogin($login);
            $user->setPassword($this->createHash($password));
            $user->setName($name);
            $user->setAddress($address);
            $user->setPhone($phone);
            $user->setBdate($bdate);

            if ($level) {
                $level = (int) $level;
                $user->setLevel($level);
            } elseif ($activate) {
                $user->setLevel(0);
                PackageLoader::Get()->import('Randomer');
                $random = Randomer_Password::Random(16, 16);

                $user->setActivatecode($random);
            } else {
                $user->setLevel(1);
            }

            if ($commentadmin) {
                $user->setCommentadmin($commentadmin);
            }

            $user->insert();

            // sendmail
            $tpl = MEDIA_PATH.'/mail-templates/registration.html';
            $sender = new MailUtils_SmartySender($tpl);
            $sender->setEmailFrom(BC::Get()->getSettingsService()->getSettingValue('header-email'));
            $sender->addEmail($email);
            $sender->assign('id', $user->getId());
            $sender->assign('login', $login);
            $sender->assign('password', $password);
            if ($activate && $level < 3 && !$logniza) {
                $sender->assign('activateURL', Engine::Get()->getProjectURL().Engine::GetLinkMaker()->makeURLByContentIDParams('account-activate', array('email' => $email, 'code' => $random)));
            }
            $sender->send();

            SQLObject::TransactionCommit();

            return $user;
        } catch (Exception $ge) {
            SQLObject::TransactionRollback();
            throw $ge;
        }
    }

    /**
     * Выслать новый пароль на почту
     *
     * @param string $login_email
     */
    public function remindPassword($login_email) {
        try {
            SQLObject::TransactionStart();

            $login_email = trim($login_email);

            try {
                $user = $this->getUserByLogin($login_email);
            } catch (Exception $e) {
                $user = $this->getUserByEmail($login_email);
            }

            PackageLoader::Get()->import('Randomer');
            $password = Randomer_Password::Random(6);
            $user->setPassword($this->createHash($password));
            $user->update();

            $tpl = MEDIA_PATH.'/mail-templates/remindpassword.html';
            $mail = BC::Get()->getSettingsService()->getSettingValue('header-email');
            $sender = new MailUtils_SmartySender($tpl);
            $sender->setEmailFrom($mail);
            $sender->addEmail($user->getEmail());
            $sender->assign('login', $user->getLogin());
            $sender->assign('password', $password);
            $sender->assign('email', $user->getEmail());
            $sender->send();

            SQLObject::TransactionCommit();
        } catch (Exception $ge) {
            SQLObject::TransactionRollback();
            throw $ge;
        }
    }

    /**
     * Обновить профайл юзера
     *
     * @param User $user
     * @param string $email
     * @param string $password
     * @param string $name
     * @param string $phone
     * @param string $address
     * @param string $bdate
     * @param string $phones
     * @param string $emails
     * @param string $urls
     * @param string $time
     * @param int $parentid
     * @param bool $check
     * @param string $commentadmin
     * @param int $managerid
     * @param string $department
     * @param int $groupid
     * @param string $login
     * @param string $avatar
     * @param string $gender
     * @param array/string $phonemore
     * @param array/string $emailmore
     */
    public function updateUserProfile(User $user, $email, $password, $name, $phone, $address, $bdate, $phones, $emails, $urls, $time, $parentid, $check = true, $commentadmin = false, $managerid = false, $department = false, $groupid = false, $login = false,
          $avatar = '', $gender = '', $phonemore = 'no change', $emailmore = 'no change'
        ) {
        try {
            SQLObject::TransactionStart();

            $name = trim($name);
            $email = trim($email);
            $phone = trim($phone);
            $address = trim($address);
            $bdate = trim($bdate);
            $phones = trim($phones);
            $emails = trim($emails);
            $urls = trim($urls);
            $time = trim($time);
            $parentid = trim($parentid);

            $ex = new ServiceUtils_Exception();

            if ($password && !Checker::Checkpassword($password)) {
                $ex->addError('password');
            }

            if (!empty($parentid)) {
                try {
                    !$this->getUserByID($parentid);
                }catch (Exception $e){
                    $ex->addError('parentid');
                }
            }
            $phonemore_notNull = array();
            if($phonemore != 'no change') {
                //сразу отберём только не нулевые значения
                $index = 0;
                $errorphone = array();
                foreach($phonemore as $ph) {
                    if($ph) {
                        if(!Checker::CheckPhone(trim(strip_tags($ph)))){
                            $errorphone[] = $index;
                        }
                        $phonemore_notNull[] = trim(strip_tags($ph));
                    }
                    $index++;
                }
                if($errorphone) {
                    $ex->addError('phonemoreIncorrect');
                }
            }

            if (!empty($phone)) {
                if (!Checker::CheckPhone($phone)){
                    $errorphone = !empty($errorphone) ? $errorphone : array();
                    $errorphone['mainphone'] = 100;//100 - фонарное значение //выделим и главный телефон, если он не корректный
                    $ex->addError('phone');
                }
            }
            if(!empty($errorphone)) {
                $ex->addError(array('errorphone'=>$errorphone));
            }

            $emailmore_notNull = array();
            if($emailmore != 'no change') {
                //сразу отберём только не нулевые значения
                $index = 0;
                $erroremail = array();
                $existsemail = array();
                foreach($emailmore as $ph) {
                    if($ph) {
                        if(!Checker::CheckEmail(trim(strip_tags($ph)))){
                            $erroremail[] = $index;
                        }else{
                            //проверим на не повторение
                            $tmp = new User();
                            $tmp->setEmail($ph);
                            if ($tmp->select() && $tmp->getId() != $user->getId()) {
                                $existsemail[] = $index;
                            }
                        }
                        //записываем не нулевые значения
                        $emailmore_notNull[] = trim(strip_tags($ph));
                    }
                    $index++;
                }
                if($erroremail) {
                    $ex->addError('emailmoreIncorrect');
                }
                if($existsemail) {
                    $ex->addError('emailmoreExist');
                }
            }

            if(!$email) {
                $ex->addError('mainemail');
            }

            if ($check && !Checker::CheckEmail($email) || ($email && !Checker::CheckEmail($email))) {
                $erroremail = !empty($erroremail) ? $erroremail : array();
                $erroremail['mainemail'] = 100;//100 - фонарное значение  выделим и главный email, если он не корректный (
                $ex->addError('email');
            } elseif ($email) {
                $tmp = new User();
                $tmp->setEmail($email);
                if ($tmp->select() && $tmp->getId() != $user->getId()) {
                    $existsemail = !empty($existsemail) ? $existsemail : array();
                    $existsemail['mainemail'] = 100;
                    $ex->addError('email-exists');
                }
            }

            if(!empty($erroremail)) {
                $ex->addError(array('erroremail'=>$erroremail));
            }
            if(!empty($existsemail)) {
                $ex->addError(array('existsemail'=>$existsemail));
            }

            /*if (!empty($bdate)) {
                if (!Checker::CheckDate($bdate)) {
                    $ex->addError('bdate');
                }
            }*/

            if ($groupid) {
                try {
                    $group = $this->getUserGroupByID($groupid);
                } catch (Exception $e){
                    $ex->addError('groupid');
                }
            }

            if ($login) {
                if (!Checker::CheckLogin($login)) {
                    $ex->addError('login');
                } else {
                    $user_test = new User();
                    $user_test->setLogin($login);
                    if ($user_test->select() && $user->getId() != $user_test->getId()) {
                        $ex->addError('login-exists');
                    }
                }
            }

            if ($ex->getCount()) {
                throw $ex;
            }

            $user->setEmail($email);
            $user->setName($name);
            $user->setGender($gender);
            if ($avatar) {
                $dir = MEDIA_PATH . 'users/'.$user->getId().'/';
                if ($dh = @opendir($dir)) {

                }else {
                    mkdir(MEDIA_PATH . 'users/'.$user->getId().'/');
                    $dh = @opendir($dir);
                }
                //удаляем старые файлы и тюмбы
                if ($dh) {
                    while (($file = readdir($dh)) !== false) {
                        @unlink($dir . $file);
                    }
                    closedir($dh);
                }

                if($avatar == 'delete'){
                    $user->setImage('');
                } else {
                    $filename = mt_rand(0, 999999) . time() . '.png';
                    copy($avatar, $dir . $filename);
                    $user->setImage($filename);
                }
            }
            $user->setAddress($address);
            $user->setPhone($phone);
            //устанавливаем дополнительные телефоны
            for($i = 0; $i <count($phonemore_notNull); $i++) {
                $j = $i+2;
                $Method = "setPhone" . $j;
                $digitalMethod = "setPhone" . $j ."digital";
                $user->$Method($phonemore_notNull[$i]);
                preg_match_all('#(\d+)#',$phonemore_notNull[$i],$pockets);
                $user->$digitalMethod(substr(implode('',$pockets[0]),-10));
            }
            //обнулим остальные поля телефонов
            for($i = count($phonemore_notNull); $i <=8; $i++) {
                $j = $i+2;
                $Method = "setPhone" . $j;
                $digitalMethod = "setPhone" . $j ."digital";
                $user->$Method('');
                $user->$digitalMethod('');
            }
            //устанавливаем дополнительные emails
            for($i = 0; $i <count($emailmore_notNull); $i++) {
                $j = $i+2;
                $Method = "setEmail" . $j;
                $user->$Method($emailmore_notNull[$i]);
            }
            //обнулим остальные поля emails
            for($i = count($emailmore_notNull); $i <=8; $i++) {
                $j = $i+2;
                $Method = "setEmail" . $j;
                $user->$Method('');
            }
            $user->setPhones($phones);//устаревшее, сейчас телефоны вводим по одному
            $user->setEmails($emails);
            $user->setBdate($bdate);
            $user->setTime($time);
            $user->setGroupid($groupid);
            if($commentadmin){
                $user->setCommentadmin($commentadmin);
            }
            if ($parentid) {
                $user->setParentid($parentid);
            }
            $user->setUrls($urls);
            if ($password) {
                $user->setPassword($this->createHash($password));
            }
            if ($managerid !== false) {
                $managerid = (int) $managerid;
                $user->setManagerid($managerid);
            }
            if ($department !== false) {
                $user->setDepartment($department);
            }
            if ($login) {
                $user->setLogin($login);
            }

            $user->update();

            SQLObject::TransactionCommit();
        } catch (ServiceUtils_Exception $ex) {
            SQLObject::TransactionRollback();
            throw $ex;
        }
    }

    /**
     * Обновить главные настройки пользователя юзера
     *
     * @param User $user
     * @param string $login
     * @param string $email
     * @param string $oldpassword
     * @param string $newpassword
     * @param string $newpasswordagain
     */
    public function updateUserProfileSecure(User $user, $login, $email, $oldpassword, $newpassword, $newpasswordagain) {
        $login = trim($login);
        $email = trim($email);

        $ex = new ServiceUtils_Exception();
        if(!$oldpassword && $email != $user->getEmail()) {
            $ex->addError('changeEmailwithoutpassword');
        }
        if($oldpassword && !$newpassword){//прислан флаг что пароль не меняется (в данной ситуации менятся могут только емаил и логин)
            if(md5($oldpassword) != $user->getPassword()){
                $ex->addError('badpassword');
            }
        }
        if($newpassword) {//ситуация когда меняется пароль
            if($newpassword != $newpasswordagain) {
                $ex->addError('badNewPassword');
            } elseif(!Checker::CheckPassword($newpassword)) {
                $ex->addError('badNewPassword');
            }
            if(md5($oldpassword) != $user->getPassword()) {
                $ex->addError('badOldPassword');
            }
        }
        if(!$email || !Checker::CheckEmail($email)) {
            $ex->addError('bademail');
        } elseif($email != $user->getEmail()) {
            $usertemp = new User();
            $usertemp->setEmail($email);
            if ($usertemp->select()) {
                $ex->addError('email-exists');
            }
        }
        if($login) {
            if (!Checker::CheckLogin($login)) {
                $ex->addError('badLogin');
            } else {
                $user = new User();
                $user->setLogin($login);
                if ($user->select()) {
                    $ex->addError('login-exists');
                }
            }
        }
        if ($ex->getCount()) {
            throw $ex;
        }

        if(!$newpassword) {//если нет нового пароля, то может менятся только логин и пароль
            $user->setEmail($email);
            $user->setLogin($login);
        } else {//можно поменять логин и пароль
            $user->setLogin($login);
            $user->setPassword(md5($newpassword));
        }
        $user->update();
    }

    public function updateUserACL(User $user, $level, $aclArray) {
        if (!$aclArray) {
            $aclArray = array();
        }

        $level = (int) $level;
        if ($level < 0) {
            throw new ServiceUtils_Exception();
        }

        try {
            SQLObject::TransactionStart();

            $user->setLevel($level);
            $user->update();

            // убираем старые ACL
            $acl = new XUserACL();
            $acl->setUserid($user->getId());
            while ($x = $acl->getNext()) {
                $x->delete();
            }

            // вставляем новые ACL
            foreach ($aclArray as $x) {
                $acl = new XUserACL();
                $acl->setUserid($user->getId());
                $acl->setAcl($x);
                $acl->insert();
            }

            SQLObject::TransactionCommit();
        } catch (Exception $ge) {
            SQLObject::TransactionRollback();
            throw $ge;
        }
    }
    /**
     * @param $emailOrLogin
     * @return int
     */
    public function findUserByEmailOrLogin($emailOrLogin) {
        $user = $this->getUsersAll();
        $user2 = clone $user;
        $user->setLogin($emailOrLogin);
        if($user->select()) {
            return $user->getId();
        }
        $user2->setEmail($emailOrLogin);
        if($user2->select()) return $user2->getId();
        return;
    }

    /**
     * Получить ACL для юзера
     *
     * @param User $user
     * @return ACL_Simple
     */
    public function getUserACL(User $user) {
        if (!isset($this->_acl[$user->getId()])) {
            // подключаем ACL
            PackageLoader::Get()->import('ACL');

            // создаем ACL
            $this->_acl[$user->getId()] = new ACL_Simple();

            // добавляем в ACL текущую роль
            $role = $this->_acl[$user->getId()]->addRole('user'.$user->getId());

            // получаем группу юзера
            // и загружаем в ACL список привелегий группы
            $list = new XUserACL();
            $list->setUserid($user->getId());
            while ($x = $list->getNext()) {
                $resource = $this->_acl[$user->getId()]->addResource($x->getAcl());
                $this->_acl[$user->getId()]->allow($role, $resource);
            }
        }
        return $this->_acl[$user->getId()];
    }

    /**
     * Получить список прав юзера в виде 2D-assoc массива
     *
     * @return array
     * @param User $user
     */
    public function getUserACLArray(User $user) {
        $acl = $this->getACLPermissions();
        $a = array();
        foreach ($acl as $x) {
            $key = str_replace('-', '_', $x['key']);
            $a[$key] = $user->isAllowed($x['key']);
        }
        return $a;
    }

    /**
     * Получить список прав доступа.
     * Метод вернет 2D-массив
     *
     * @return array
     */
    public function getACLPermissions() {
        $xml = simplexml_load_string(file_get_contents(dirname(__FILE__).'/../acl/acl.xml'));
        $a = array();
        foreach ($xml->acl as $acl) {
            $a[] = array(
            'name' => $acl->name.'',
            'key' => $acl->key.'',
            // 'parentkey' => $acl->parent.'',
            );
        }

        /*// ACL по группам пользователей
        $userGroups = $this->getUserGroupsAll();
        $actions = array(
        array('key' => 'view', 'name' => 'Просматривать пользователей группы'),
        array('key' => 'edit', 'name' => 'Редактировать пользователей группы')
        );

        while ($group = $userGroups->getNext()) {
            foreach ($actions as $action) {
                $a[] = array(
                'name' => 'Пользователи: Управление группами: '.$group->getName().': '.$action['name'],
                'key' => 'users-group-'.$group->getId().'-'.$action['key']
                );
            }
        }

        // ACL по категориям туризма
        $tourismCategory = BC::Get()->getTourismService()->getTourismCategoryAll();
        while ($tc = $tourismCategory->getNext()) {
            $a[] = array(
                'name' => 'Туризм: '.$tc->getName(),
                'key' => 'tourismCategory'.$tc->getId(),
            );
        }*/

        usort($a, array($this, '_sortACL'));
        return $a;
    }

    private function _sortACL($a, $b) {
        return $a['name'] > $b['name'];
    }

    /**
     * Быстро зарегистрировать пользователя-клиента
     *
     * @param string $clientName
     * @param string $login
     * @param string $password
     * @param string $email
     * @param string $phone
     * @param string $address
     * @return User
     */
    public function addUserClient($clientName, $login = false, $password = false, $email = false, $phone = false, $address = false) {
        try {
            SQLObject::TransactionStart();

            $clientName = trim($clientName);
            if (!$clientName) {
                throw new ServiceUtils_Exception();
            }

            $user = new User();
            $user->setName($clientName);

            if (!$user->select()) {

                if ($login) {
                    $user1 = new User();
                    $user1->setLogin($login);

                    if (Checker::CheckLogin($login) && !$user1->select()) {
                        $user->setLogin($login);
                    }
                }

                if ($password) {
                    if (Checker::CheckPassword($password)) {
                        $user->setPassword(md5($password));
                    }
                }

                if ($email) {
                    $user1 = new User();
                    $user1->setEmail($email);
                    if (Checker::CheckEmail($email) && !$user1->select()) {
                        $user->setEmail($email);
                    }
                }

                $user->setAddress($address);
                $user->setPhone($phone);

                $user->setLevel(0);
                $user->setCdate(date('Y-m-d H:i:s'));
                $user->insert();
            }

            SQLObject::TransactionCommit();

            return $user;
        } catch (Exception $ge) {
            SQLObject::TransactionRollback();
            throw $ge;
        }
    }

    /**
     * Поиск пользователей и клиентов
     *
     * @param string $query
     * @return User
     */
    public function searchUsers($query) {
        $query = trim($query);
        if (strlen($query) < 3) {
            throw new ServiceUtils_Exception();
        }

        // перестановки всех слов
        $a = array();
        if (preg_match_all("/([\.\d\pL]+)/ius", $query, $r)) {
            foreach ($r[1] as $part) {
                $a[] = mysql_escape_string($part);
            }
        }

        if (!$a) {
            throw new ServiceUtils_Exception();
        }

        $users = $this->getUsersAll();

        foreach ($a as $part) {
            $w = array();

            $w[] = "id ='$part'";
            $w[] = "name LIKE '%$part%'";
            $w[] = "login LIKE '%$part%'";
            $w[] = "email LIKE '%$part%'";
            $w[] = "phone LIKE '%$part%'";
            $w[] = "address LIKE '%$part%'";

            // превращаем в en транскрипцию
            try {
                $partTr = StringUtils_Transliterate::TransliterateRuToEn($part);

                $partTr = mysql_escape_string($partTr);

                $w[] = "name LIKE '%$partTr%'";
            } catch (Exception $e) {

            }

            // превращаем ru
            try {
                $partRu = StringUtils_Transliterate::TransliterateCorrectTo('ru', $part);

                $partRu = mysql_escape_string($partRu);

                $w[] = "name LIKE '%$partRu%'";
            } catch (Exception $e) {

            }

            // превращаем en
            try {
                $partEn = StringUtils_Transliterate::TransliterateCorrectTo('en', $part);

                $partEn = mysql_escape_string($partEn);

                $w[] = "name LIKE '%$partEn%'";
            } catch (Exception $e) {

            }

            $users->addWhereQuery("(".implode(' OR ', $w).")");
        }

        return $users;
    }

    /**
     * Получить всех юзеров
     *
     * @return User
     */
    public function getUsersAllOrderDesc() {
        $x = $this->getObjectsAll();
        $x->setOrder('id', 'DESC');
        return $x;
    }

    /**
     * @return ShopUserGroup
     */
    public function getUserGroupByID($id) {
        try {
            return $this->getObjectByID($id, 'ShopUserGroup');
        } catch (Exception $e) {}
        throw new ServiceUtils_Exception('ShopUserGroup by id not found');
    }

    /**
     * @return ShopUserGroup
     */
    public function getUserGroupsAll() {
        $x = new ShopUserGroup();
        return $x;
    }

    /**
     * Получить массив групп пользователей, в которых текущему пользователю разрешена операция
     *
     * @param string $operation
     * @return array
     */
    public function getUsersGroups($operation) {
        $user = $this->getUser();
        $groups = $this->getUserGroupsAll();
        $groupsArray = array();
        while ($group = $groups->getNext()) {
            if ($user->isAllowed('users-group-'.$group->getId().'-'.$operation)) {
                $groupsArray[] = array(
                'id' => $group->getId(),
                'name' => $group->getName(),
                'url' => Engine::Get()->GetLinkMaker()->makeURLByContentIDParam('admin-users', $group->getId(), 'groupid')
                );
            }
        }
        return $groupsArray;
    }

    /**
     * @param ShopUserGroup $storageName
     * @param string $operation
     * @return boolean
     */
    public function isUserGroupOperationAllowed($userGroup, $operation) {
        $user = $this->getUser();
        return $user->isAllowed('users-group-'.$userGroup->getId().'-'.$operation);
    }

    /**
     * Выслать письмо пользователю на почту
     *
     * @param $name
     * @param $email
     * @param $mail
     * @param $subject
     * @param $text
     * @throws Exception
     */
    public function sendEmail($name, $email, $mail, $subject, $text) {
        try {
            SQLObject::TransactionStart();

            $subject = trim($subject);
            $text = trim($text);
            $mail = trim($mail);
            $email = trim($email);

            if (!$email) {
                throw new ServiceUtils_Exception();
            }
            if (!Checker::CheckEmail($mail)) {
                throw new ServiceUtils_Exception();
            }
            if (!$text) {
                throw new ServiceUtils_Exception();
            }

            $text = str_replace('[name]', $name, $text);
            $text = str_replace('[email]', $email, $text);

            $tpl = MEDIA_PATH.'/mail-templates/shop-mass-mailing.html';
            $sender = new MailUtils_SmartySender($tpl);
            $sender->setEmailFrom($mail);
            $sender->addEmail($email);
            $sender->assign('name', $name);
            $sender->assign('subject', $subject);
            $sender->assign('text', $text);
            $sender->send();

            SQLObject::TransactionCommit();
        } catch (Exception $ge) {
            SQLObject::TransactionRollback();
            throw $ge;
        }
    }

    /**
     * @param $email
     * @param $code
     * @throws Exception
     * @throws ServiceUtils_Exception
     */
    public function activateUser($email, $code) {
        try {
            $user = new User();
            $user->setEmail($email);
            $user->setActivatecode($code);
            $user->setLevel(0);
            $user->setLimitCount(1);

            if (!$user->select()) {
                throw new ServiceUtils_Exception();
            }

            $user->setLevel(1);
            $user->setActivatecode('');

            $user->update();

            return $user;
        } catch (Exception $ge) {
            throw $ge;
        }
    }

    /**
     * @return UserBalance
     */
    public function getUserBalanceRecordsAll() {
        $x = new UserBalance();
        $x->setOrder('cdate', 'DESC');
        return $x;
    }

    /**
     * @param int $userID
     * @return UserBalance
     */
    public function getUserBalanceRecordsByUserID($userID) {
        $x = $this->getUserBalanceRecordsAll();
        $x->setUserid($userID);
        return $x;
    }

    /**
     * @param User $user
     * @param int $sum
     * @param string $comment
     * @return UserBalance
     */
    public function incUserBalance(User $user, $sum, $comment, $operatorID = false) {
        $sum = (float) $sum;
        if ($sum <= 0) throw new ServiceUtils_Exception('sum');

        try {
            $operator = $this->getUserByID($operatorID);
        } catch (Exception $e) {
            $operator = $this->getUser();
        }

        $x = new UserBalance();
        $x->setUserid($user->getId());
        $x->setAmount($sum);
        $x->setComment($comment);
        $x->setOperatorid($operator->getId());
        $x->setCdate(date('Y-m-d H:i:s'));
        $x->insert();
        return $x;
    }

    /**
     * @param User $user
     * @param int $sum
     * @param string $comment
     * @return UserBalance
     */
    public function decUserBalance(User $user, $sum, $comment, $companyid = false) {
         $sum = (float) $sum;
         if ($sum < 0) $sum = (-1) * $sum;
         if ($sum == 0) throw new ServiceUtils_Exception('sum');

        $x = new UserBalance();
        $x->setUserid($user->getId());
        $x->setAmount(-$sum);
        $x->setComment($comment);
        if ($this->getUserSecure()) {
            $operator = $this->getUserSecure();
        } else {
            //Если деньги снимаютсья и нету пользователя, хначит данные пришли через curl() от Интеркассы
            try {
                $operator= BC::Get()->getUserService()->getUserByLogin('interkassa');
            } catch (Exception $e){
                $operator = $user;
            }
        }
        if ($companyid) {
            $x->setCompanyid($companyid);
        }
        
        $x->setOperatorid($operator->getId());   
        $x->setCdate(date('Y-m-d H:i:s'));
        $x->insert();
        return $x;
    }

    /**
     * @param User $user
     * @return UserBalance
     */
    public function getUserBalance($user) {
        $x = new UserBalance();
        $x->setUserid($user->getId());
        $x->addFieldQuery("SUM(`amount`) as 'sum'");
        $x->setGroupByQuery('userid');
        if ($y = $x->getNext()) {
            return $y->getField('sum');
        } else {
            return 0;
        }
    }

    /**
     * @param User $user
     * @param $password
     */
    public function checkPassword($user,$password) {
        return $user->getPassword() == md5($password);
    }

    /**
     * @param $userid
     */
    public function deleteUser($userid) {
        //@todo добавлять удаления при добавлении связей
        //удалим компании юзера
        $company = BC::Get()->getCompanyService()->getCompanyByUserID($userid);
        while($c = $company->getNext()){
            BC::Get()->getCompanyService()->deleteCompany($c->getId());
        }
        //удаляем объявления
        $announ = BC::Get()->getAnnouncementService()->getAnnouncementsByUserId($userid);
        while($a = $announ->getNext()){
            BC::Get()->getAnnouncementService()->deleteAnnouncement($a->getId());
        }

        //@todo пока просто удяляю запись новости, потом возможно нужно будет использовать метод удаления(связи, изображения)?
        $news = BC::Get()->getNewsService()->getNewsByUserid($userid);
        while($n = $news->getNext()){
            $n->delete();
        }
        //@todo тоже по недвижимости?
        $realestate = BC::Get()->getRealestateService()->getRealestateByUserID($userid);
        while($r = $realestate->getNext()){
            $r->delete();
        }
        //@todo тоже по subscribe?
        $sub = BC::Get()->getSubscribeService()->getSubscribeByUserID($userid);
        while($s = $sub->getNext()){
            $s->delete();
        }

        $user = $this->getUserByID($userid)->delete();

    }

}